package com.zh.demo04.verifycode;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;


/**
 * sms验证码的校验Filter
 * 请求接口需要携带验证码参数 verifyCode
 */
@Slf4j
@AllArgsConstructor
public class VerifyCodeSmsCheckFilter extends OncePerRequestFilter {
    /**请求时 验证码参数的name*/
     static final String VERIFY_CODE_PARAM = "verifyCode";

    /**验证码生成抽象类*/
    private VerifyCodeService verifyCodeService;

    protected AuthenticationFailureHandler myAuthenticationFailureHandler;

    @Override
    final protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (isRequiredCheckUrl(request)){
            try{
                checkVerificationCode(request);
                log.info("验证码 校验通过");
            }catch (AuthenticationException ex){
                log.warn("验证码 校验未通过。 {}", ex.getMessage());
                myAuthenticationFailureHandler.onAuthenticationFailure(request, response, ex);
                return;
            }
        }

        filterChain.doFilter(request,response);
    }

    /**
     * 判断访问url需要做验证码检查
     * 当请求url是指定需要检查的，而且必须是POST方式，才执行检查验证码操作
     * @param request
     * @return
     */
    private boolean isRequiredCheckUrl(HttpServletRequest request) {
        if (!"POST".equalsIgnoreCase(request.getMethod()))
            return false;

        var requestURI = request.getRequestURI();

        // 假设/login接口需要验证码校验
        return "/login".equalsIgnoreCase(requestURI);
    }

    /**
     * 进行验证码的校验
     * @param request
     */
    private void checkVerificationCode(HttpServletRequest request) {
        //获取客户端的提交的验证码value 和 服务端的验证码对象
        String codeValue = request.getParameter(VERIFY_CODE_PARAM);

        verifyCodeService.validate(request,codeValue);

        log.debug("验证码对比成功：codeValue = {}",codeValue);
    }
}
